package com.sky.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.annotation.AutoFill;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.Employee;
import com.sky.enumeration.OperationType;
import com.sky.exception.*;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.Result;
import com.sky.service.EmployeeService;
import com.sky.vo.EmployeePageVO;
import com.sky.vo.EmployeeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();
        // 计算密码的MD5值,因为数据库存的是密码的MD5值
        String passwordMD5 = DigestUtil.md5Hex(password);
        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        //  后期需要进行md5加密，然后再进行比对
        if (!passwordMD5.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }
        Long id = employee.getId();
        BaseContext.setCurrentId(new UserThredDTO(employee.getId()));
        log.info("登录成功,线程空间中存入登录人的信息{}",BaseContext.getCurrentId());
        //3、返回实体对象
        return employee;
    }
    
    /**
     * 新增员工信息
     * @author: XieMingHui 
     * @date: 23/11/17 10:06:40
     * @param: [employeeDTO]
     * @return: com.sky.result.Result<java.lang.String>
     **/
    @Override
    @Transactional
    //@AutoFill(value = OperationType.INSERT) //自定义注解用于切面类通知
    public Result<String> addEmployee(EmployeeDTO employeeDTO) {
        Employee employee = BeanUtil.toBean(employeeDTO, Employee.class);
        Console.log(employee);
        employee.setPassword(DigestUtil.md5Hex(PasswordConstant.DEFAULT_PASSWORD));
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId().getId();
        employee.setCreateTime(now);
        employee.setUpdateTime(now);
        employee.setCreateUser(currentId);
        employee.setUpdateUser(currentId);
        boolean save = save(employee);
        if (!save) {
            return Result.error("新增失败");
        }
        return Result.success();
    }
    /**
     * 分页查询员工
     * @author: XieMingHui
     * @date: 23/11/20 21:24:06
     * @param: [e]
     * @return: com.sky.result.Result<com.sky.vo.EmployeePageVO>
     **/
    @Override
    public Result<EmployeePageVO> findEmployee(EmployeePageQueryDTO e) {
        String name = e.getName();
        Page<Employee> page = lambdaQuery().eq(StrUtil.isNotBlank(name), Employee::getName, name)
                .page(new Page<>(e.getPage(), e.getPageSize()));
        List<Employee> employeeList = page.getRecords();
        List<EmployeeVO> employeeDTOS = new ArrayList<>();
        for (Employee employee : employeeList) {
            employeeDTOS.add(BeanUtil.toBean(employee, EmployeeVO.class));
        }
        return Result.success(new EmployeePageVO(employeeDTOS, page.getTotal()));
    }

    /**
     * 修改密码
     * @author: XieMingHui
     * @date: 23/11/17 10:36:17
     * @param: [passwordEditDTO]
     * @return: com.sky.result.Result<java.lang.String>
     **/
    @Override
    @Transactional
    public Result<String> updatePassword(PasswordEditDTO passwordEditDTO) {
        UserThredDTO userThredDTO = BaseContext.getCurrentId();
        if (userThredDTO==null ){
            throw new UserNotLoginException(MessageConstant.USER_NOT_LOGIN);
        }
        Long empId = userThredDTO.getId();
        Employee byId = getById(empId);
        if (BeanUtil.isEmpty(byId)) {
            // 账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        String md5HexPassword = DigestUtil.md5Hex(passwordEditDTO.getOldPassword());
        if (!byId.getPassword().equals(md5HexPassword)) {
            // 旧密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        LambdaUpdateWrapper<Employee> wrapper = new UpdateWrapper<Employee>().lambda()
                .eq(Employee::getId, empId)
                .set(Employee::getPassword, DigestUtil.md5Hex(passwordEditDTO.getNewPassword()));
        boolean update = update(wrapper);
        if (!update){
            // 修改失败
           throw new PasswordEditFailedException(MessageConstant.PASSWORD_EDIT_FAILED);
        }
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    /**
     * 修改员工账号状态
     * @author: XieMingHui
     * @date: 23/11/17 9:27:55
     * @param: [状态值, 账号id]
     * @return: com.sky.result.Result<java.lang.String>
     **/
    public Result<String> enablingDisabling(Long status, Long id) {
        UserThredDTO current = BaseContext.getCurrentId();
        log.info("查找线程空间里的数据:{}",current);
        if (current==null){
            throw new UserNotLoginException(MessageConstant.USER_NOT_LOGIN);
        }
        if (current.getId()==1L){
            LambdaUpdateWrapper<Employee> wrapper = new UpdateWrapper<Employee>().lambda()
                    .eq(Employee::getId, id)
                    .set(status >= 0, Employee::getStatus, status);
            boolean update = update(wrapper);
            if (!update){
                throw new BaseException("修改失败");
            }else {
                return Result.success();
            }
        }else {
            throw new RuntimeException("没有权限");
        }
    }

    /**
     * 根据id查询员工信息
     * @author: XieMingHui
     * @date: 23/11/17 9:34:32
     * @param: [id]
     * @return: com.sky.result.Result<com.sky.vo.EmployeeVO>
     **/
    @Override
    public Result<EmployeeVO> findEmpById(Long id) {
        if (id==null){
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        Employee employee = getById(id);
        if (employee==null){
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        EmployeeVO employeeVO = BeanUtil.toBean(employee, EmployeeVO.class);
        return Result.success(employeeVO);
    }

    /**
     * 修改员工信息
     * @author: XieMingHui
     * @date: 23/11/17 9:48:47
     * @param: [employeeDTO]
     * @return: com.sky.result.Result<java.lang.String>
     **/
    @Override
    @Transactional
    public Result<String> editingEmp(EmployeeDTO employeeDTO) {
        if (employeeDTO==null){
            return  Result.error("修改失败");
        }
        Employee employee = BeanUtil.toBean(employeeDTO, Employee.class);
        boolean updateById = employee.updateById();
        if (!updateById){
            return  Result.error("修改失败");
        }
        return Result.success();
    }

}
